# -*- coding:utf-8 -*-
# @Time  : 2019/12/3 18:55
# @Author: wangxb
'''
根据提供的应用宝地址，进行下载apk、获取apk中的微信ID
'''

import datetime
import os
import time

from classes.requestOperation import jsonPaser, downloadAPK
from classes.searchContent import examineDirectory, read_zipFile, FindConetent
from classes.jarOperation import generateJarFile, examZipFile, getAllClassesFileInAPK, changeFileSuffix, copyAPKToZip, \
    killJdgui
from classes.threadOperation import JdguiThread, KeyboardThread

# 需要爬取apk的网址（应用宝）
apkUrl = 'https://sj.qq.com/myapp/cate/appList.htm?orgame=1&categoryId=109&pageSize=3&pageContext=0'
# apk包名
# apk_name = 'com.tencent.mm.apk'
# 不需要解析的app数组
appList = ["平安好医生", "WPS Office", "企查查企业信用查询", "扫描全能王", "企业微信", "钉钉", "小影-微视频DIY神器", "荔枝", "酷音铃声-铃声大全", "爱音乐",
           "QQ空间", "MOMO陌陌", "派派", "探探", "4399游戏盒", "美柚-大姨妈月经期助手", "腾讯微博"]
# 项目的根路径
root_path = os.path.dirname(os.getcwd())
# apk文件路径
apk_file_path = root_path + os.sep + 'APKSources' + os.sep
# apk的zip文件路径
# apk_zip_file_path = ''
# 反编译后的zip文件路径
jar_zip_file_path = root_path + os.sep + 'zipSources'
# lanchon_tools工具所在路径
lanchon_tools_path = root_path + os.sep + 'dex-tools-lanchon'
# 搜索文件的根路径
searchRootPath = root_path + os.sep + 'zipSources' + os.sep + 'classes-dex2jar.src'
# 搜索结果输出路径s
outputPath = root_path + os.sep + 'output_files.txt'


def totalProcess(apk_file_path):
    # apk_zip_file_path = None
    try:
        # apk的zip文件路径
        apk_zip_file_path = changeFileSuffix(apk_file_path)
        # 获取对应apk的zip包
        copyAPKToZip(apk_file_path, apk_zip_file_path)
        # 获取APK对应zip包中的classes.dex文件
        classes_list = []
        classes_list = getAllClassesFileInAPK(apk_zip_file_path)

        for classes_file in classes_list:
            try:
                print(
                    '\n#############################Start decompile ' + classes_file + '#############################')
                # 生成apk对应的jar包文件
                generateJarFile(apk_zip_file_path, lanchon_tools_path, classes_file)

                # 调用jd-gui工具
                t = JdguiThread("jdguiThread", lanchon_tools_path)
                t.start()

                # 判断dex2jar的zip文件是否存在，存在则删除
                examZipFile(jar_zip_file_path)
                time.sleep(2)

                # 调用快捷键，另存为classes-dex2jar.src.zip
                t2 = KeyboardThread("keyboardThread", jar_zip_file_path)
                t2.start()

                # 主线程等25s，保存大的zip文件
                time.sleep(30)

                # 检测jd-gui进程是否还存在。存在返回0，则超时结束进程
                killJdgui()

                # 避免[WinError 32]提示另一个程序正在使用此文件，进程无法访问异常
                time.sleep(2)
                # 删除之前搜索目录中遗留的文件
                examineDirectory(searchRootPath)

                # 解压classes-dex2jar.src.zip文件
                read_zipFile(jar_zip_file_path, searchRootPath)

                # 根据关键字搜索指定路径下所有文件的内容
                findObj = FindConetent(searchRootPath)
                findObj.find_file(findObj)
                findObj.walk(findObj, outputPath, apk_file_path)
            except Exception as e:
                print(e)
            finally:
                # 系统卡住主动结束jd-gui进程，以防影响解析后续的jar
                killJdgui()

    except BaseException as errors:
        print(errors)
    finally:
        # 删除对应apk的zip包
        os.remove(apk_zip_file_path)


if __name__ == '__main__':
    start = datetime.datetime.now()
    # 获取所有app下载对象数组
    objList = jsonPaser(apkUrl)
    objLength = len(objList)
    # 对数组中的apk进行解析
    for i in range(objLength):
        try:
            # 在输出文件中区分每个app的微信ID
            f = open(outputPath, "a", encoding='utf-8')
            # 依次遍历下载app
            apkUrl = objList[i]["apkUrl"]
            appName = objList[i]["appName"]
            # 如果下载的app名称在appList中，则跳过解析
            if appName in appList:
                continue
            f.write('\n#############################Start An APP##################################\n')
            f.write('appName==' + appName)
            f.close()
            pkgName = objList[i]["pkgName"] + '.apk'
            apk_file_path_final = apk_file_path + pkgName
            # 根据apk的下载URL下载对应的apk
            print("#######################Start download " + appName + "#######################")
            downloadAPK(apkUrl, apk_file_path_final)
            print("#######################Finished download " + appName + "#######################")
            # 获取apk后，进行后续的dex2jar和jd-gui，以及search
            totalProcess(apk_file_path_final)
            f = open(outputPath, "a", encoding='utf-8')
            f.write('#############################End An APP##################################\n')
        except BaseException as error:
            print(error)
        finally:
            f.close()
    end = datetime.datetime.now()
    print('Running time: %s Seconds' % (end - start))
